package mt.filter;

import static org.junit.Assert.assertEquals;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import mt.Order;
import mt.comm.ServerSideMessage;
import mt.dummy.ServerCommDummy;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Test battery for Printing average order(Buy/Sell) number each minute, with the system clock.
 * @author maraa@iscte-iul.pt
 *
 */

public class AnalyticsFilterPrintStatisticsRealTest {
	/**
	 * This unit test initialises an AnalyticsFilter which a ServerCommDummy as
	 * parameter.
	 */
	private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
	private ServerCommDummy serverCommDummy;
	private AnalyticsFilter analyticsFilter;

	/**
	 * Fills a ServerComm ServerSideMessage with 3 messages that contain the
	 * same type, same SenderNickname and same order.
	 */
	@Before
	public void setUpFilter() {
		
		serverCommDummy = new ServerCommDummy();
		analyticsFilter = new AnalyticsFilter(serverCommDummy);

		// Three messages are going to be created
		for (int i = 0; i < 3; i++) {
			serverCommDummy.getListOfMessages().add(new ServerSideMessage() {

				@Override
				public Type getType() {
					return Type.NEW_ORDER;
				}

				@Override
				public String getSenderNickname() {
					return "batata";
				}

				@Override
				public Order getOrder() {
					return Order.createBuyOrder(null, null, 0, 0);
				}
			});
		}

		System.setOut(new PrintStream(outContent));
	}

	@After
	public void cleanUpStreams() {
		System.setOut(null);
	}

	/*
	 * SystemClock is initialized, so we have better time control. Tests if is
	 * printed on console every 1 minute the average of orders.
	 */

	@Test
	public void testprintStatisticsMessage() throws InterruptedException,
			IOException {
		analyticsFilter.start();

		Thread.sleep(40000);
		// Clock = 40s
		assertEquals("", outContent.toString());
		// No statistics must be shown, since the first minute has not been
		// reached

		analyticsFilter.getNextMessage();
		// first order was recived
		Thread.sleep(25000);
		// Clock = 65s
		assertEquals(
				"Average orders received per minute: 1.0"
						+ System.lineSeparator(), outContent.toString());
		outContent.reset();

		Thread.sleep(60000);
		// clock = 125s, 2 minute passed
		assertEquals(
				"Average orders received per minute: 0.0"
						+ System.lineSeparator(), outContent.toString());
		// The Average is 0.0, since order counter was reseted
		outContent.reset();

		analyticsFilter.getNextMessage();
		analyticsFilter.getNextMessage();
		// Get more two messages from the queue
		Thread.sleep(60000);
		// clock = 185s, 3 minute passed
		assertEquals(
				"Average orders received per minute: 2.0"
						+ System.lineSeparator(), outContent.toString());

	}

}
